import db from '../lib/db';
import {
  hideObjectKeysWithoutValues,
  hideSelectedObjectKeys,
} from '../helpers/utilsJS';
import { deleteFromCache, setExCache } from '../helpers/redis';
import log from "../helpers/logger";
//#region AutoCreateCode
import { RequestParserService } from '../lib/request-parser/src';

export async function createEntity(entity) {
  try {
    entity = hideSelectedObjectKeys(entity, ['id']);
    const newEntity = await db.table_name.create({
      data: {
        ...entity
      },
    });
    //Cache after create
    // setExCache(newEntity.id, 3600, JSON.stringify(newEntity));
    return newEntity;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function editEntityInDatabase(updatedEntity, entityId) {
  try {
    updatedEntity = hideSelectedObjectKeys(updatedEntity, ['id']);
    updatedEntity = hideObjectKeysWithoutValues(updatedEntity);
    const nowTimestamp = Date.now();
    const date = new Date(nowTimestamp);
    const withTimezone = date.toISOString();
    updatedEntity.updated_at = withTimezone; 
    if(updatedEntity.deleted_at === "0"){  //recycle data
      const entityFromDb = await db.table_name.update({
        data: { deleted_at: { set: null } },
        where: {
          id: entityId,
        },
      });
      //Cache after edit
      // setExCache(entityFromDb.id, 3600, JSON.stringify(entityFromDb));
      if (!entityFromDb) return null;
      return entityFromDb;
    }else{
      
      const entityFromDb = await db.table_name.update({
        data: updatedEntity,
        where: {
          id: entityId,
        },
      });
      //Cache after edit
      // setExCache(entityFromDb.id, 3600, JSON.stringify(entityFromDb));
      if (!entityFromDb) return null;
      return entityFromDb;
    }
    
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function editMultiEntityInDatabase(updatedEntity, ids) {
  try {
    updatedEntity = hideSelectedObjectKeys(updatedEntity, ['id','ids']);
    updatedEntity = hideObjectKeysWithoutValues(updatedEntity);
    const nowTimestamp = Date.now();
    const date = new Date(nowTimestamp);
    const withTimezone = date.toISOString();
    updatedEntity.updated_at = withTimezone; 
    if(updatedEntity.deleted_at === "0"){  //recycle data
      const entityFromDb = await db.table_name.updateMany({
        data: { deleted_at: { set: null } },
        where: {
          id: {in:ids},
        },
      });
      if (!entityFromDb) return null;
      return entityFromDb;
    }else{
      const entityFromDb = await db.table_name.updateMany({
        data: updatedEntity,
        where: {
          id: {in:ids},
        },
      });
      if (!entityFromDb) return null;
      return entityFromDb;
    }
    
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function deleteEntityFromDatabase(entityId,force = 0) {
  try {
    if(force){  //real delete data
      await db.table_name.delete({
        where: {
          id: entityId,
        },
      });
    }else{  //soft delete
      const nowTimestamp = Date.now();
    const date = new Date(nowTimestamp);
    const withTimezone = date.toISOString();
      await db.table_name.update({
        data: {deleted_at:withTimezone},
        where: {
          id: entityId,
        },
      });
    }
    // deleteFromCache(entityId);
    return true;
  } catch {
    return false;
  }
}

export async function deleteMultiEntityFromDatabase(ids,force = 0) {
  try {
    if(force){  //real delete multi data
      await db.table_name.deleteMany({
        where: {
          id:{in:ids},
        },
      });
    }else{  //soft delete
      const nowTimestamp = Date.now();
    const date = new Date(nowTimestamp);
    const withTimezone = date.toISOString();
      await db.table_name.updateMany({
        data: {deleted_at:withTimezone},
        where: {
          id: {in:ids},
        },
      });
    }
    // deleteFromCache(entityId);
    return true;
  } catch {
    return false;
  }
}

export async function getEntityFromDatabase(entityId) {
  try {
    const entityFromDb = await db.table_name.findFirst({
      where: {
        id: entityId,
      },
    });
    if (!entityFromDb) return null;
    return entityFromDb;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function getEntitysFromDatabase(limit, page, skip) {
  try {
    const entitysFromDb = await db.table_name.findMany({
      skip: limit * page + skip,
      take: limit,
    });
    if (!entitysFromDb) return null;
    return entitysFromDb;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function queryEntitysFromDatabase(limit, page, skip, query) {
  try {
    const requestParserService = new RequestParserService();
    const parsedQuery = requestParserService.parseQuery(query);
    const filter = parsedQuery.filter;
    const entitysFromDb = await db.table_name.findMany({
      skip: limit * page + skip,
      take: limit,
      where: filter,
      orderBy: parsedQuery.sort,
    });
    if (!entitysFromDb) return null;
    return entitysFromDb;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function countEntitys() {
  try {
    const totalCount = await db.table_name.count();
    return totalCount;
  } catch (e) {
    log.error(e);
    return false;
  }
}
//#endregion AutoCreateCode